package com.shelpe.services.sinbad.controller;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.shelpe.services.sinbad.controller.AdgroupController.AdgroupDto;
import com.shelpe.services.sinbad.dao.KeywordMapper;
import com.shelpe.services.sinbad.entity.jpa.Adgroup;
import com.shelpe.services.sinbad.entity.jpa.AdgroupLog;
import com.shelpe.services.sinbad.entity.jpa.Campaign;
import com.shelpe.services.sinbad.entity.jpa.Campaign.Area;
import com.shelpe.services.sinbad.entity.jpa.Campaign.ScheduleObject;
import com.shelpe.services.sinbad.entity.jpa.CampaignLog;
import com.shelpe.services.sinbad.entity.jpa.DriveType;
import com.shelpe.services.sinbad.entity.jpa.OnlineStatus;
import com.shelpe.services.sinbad.entity.jpa.User;
import com.shelpe.services.sinbad.entity.jpa.vo.AdgroupVo;
import com.shelpe.services.sinbad.entity.jpa.vo.CampaignVo;
import com.shelpe.services.sinbad.entity.jpa.vo.ConvertPlatformVo;
import com.shelpe.services.sinbad.entity.jpa.vo.PlatformVo;
import com.shelpe.services.sinbad.model.Keyword;
import com.shelpe.services.sinbad.model.KeywordExample;
import com.shelpe.services.sinbad.model.RptKeywordParam;
import com.shelpe.services.sinbad.repository.jpa.AdgroupLogRepository;
import com.shelpe.services.sinbad.repository.jpa.AdgroupRepository;
import com.shelpe.services.sinbad.repository.jpa.CampaignLogRepository;
import com.shelpe.services.sinbad.repository.jpa.CampaignRepository;
import com.shelpe.services.sinbad.repository.jpa.UserRepository;
import com.shelpe.services.sinbad.service.PlatformService;
import com.shelpe.services.sinbad.service.RptKeywordService;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.CampaignAreaDto;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.CampaignAreaResponse;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.CampaignBudgetDto;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.CampaignBudgetResponse;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.CampaignPlatformDto;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.CampaignPlatformResponse;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.CampaignScheduleDto;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.CreateCampaignResponse;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.UpdateCampaignAreaResponse;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.UpdateCampaignBudgetResponse;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.UpdateCampaignPlatformResponse;
import com.shelpe.services.sinbad.service.simbaproxy.CampaignClient.UpdateCampaignScheduleResponse;
import com.shelpe.services.sinbad.utils.CampaignUtils;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Controller
@RequestMapping("/sinbadservice/campaigns")
@Slf4j
public class CampaignController {

	@Autowired
	private CampaignLogRepository campaignLogRepository;
	@Autowired
	private AdgroupLogRepository adgroupLogRepository;
	@Autowired
	private UserRepository userRepository;
	@Autowired
	private CampaignRepository campaignRepository;
	@Autowired
	private CampaignClient campaignClient;
	@Autowired
	private ObjectMapper objectMapper;

	@Autowired
	private RptKeywordService rptKeywordService;

	@Autowired
	private PlatformService platformService;

	@Autowired
	private KeywordMapper keywordMapper;

	@Autowired
	private AdgroupRepository adgroupRepository;

	@RequestMapping(method = RequestMethod.POST, path = "")
	@ResponseBody
	public CampaignDto createCampaign(@RequestBody CampaignDto dto) {
		log.info("begin createCampaign: {}", dto);
		User user = this.userRepository.findOne(dto.getUserID());
		Assert.notNull(user, "user_not_foud");

		int existingCount = this.campaignRepository.countByUserID(user.getUserID());
		Assert.isTrue(existingCount < 8, "exceed_max_limit");

		log.info("开始创建推广计划: {},{},{}", user, dto, existingCount);
		CreateCampaignResponse res = this.campaignClient.createCampaign(user.getNick(), dto.getTitle());
		log.info("************:{},{},{}", res, user.getNick(), dto.getTitle());
		if (res != null && res.getRes() != null && res.getRes().getCampaign() != null) {
			CampaignClient.CampaignDto tbDto = res.getRes().getCampaign();
			log.info("sync to taobao: {}", tbDto);

			Campaign campaign = new Campaign();
			BeanUtils.copyProperties(tbDto, campaign);
			campaign.setAutoID(tbDto.getCampaignID());
			campaign.setAutoType(DriveType.from(dto.getAutoType()));
			campaign.setSettleStatus(OnlineStatus.from(tbDto.getSettleStatus()));
			campaign.setOnlineStatus(OnlineStatus.from(tbDto.getOnlineStatus()));
			campaign.setIncrementalPrice("");
			campaign.setPlatform("投放平台设置JSON字符串");
			campaign.setUseSmooth(true);
			campaign.setUserID(dto.getUserID());
			campaign.setUpdatedTime(new Date());
			campaign.setTitle(dto.getTitle());

			log.info("****推广计划一号****: {}", campaign);
			this.campaignRepository.save(campaign);

			if (dto.getBudget() >= 30) {
				UpdateCampaignBudgetResponse ucbRes = this.campaignClient.updateCampaignBudget(user.getNick(),
						campaign.getAutoID(), dto.getBudget(), true);
				if (ucbRes != null && ucbRes.getRes() != null && ucbRes.getRes().getBudget() != null) {
					CampaignBudgetDto tbBudgetDto = ucbRes.getRes().getBudget();
					campaign.setBudget(tbBudgetDto.getBudget());
					campaign.setUseSmooth(tbBudgetDto.isUseSmooth());
					campaign.setUpdatedTime(new Date());
					log.info("****推广计划updateCampaignBudget****: {}", campaign);
					this.campaignRepository.save(campaign);
				}
				if (ucbRes != null && ucbRes.getError() != null && ucbRes.getError().getSubMessage() != null) {
					log.error("updateCampaignBudget : {}", ucbRes.getError().getSubMessage());
				}
			} else {
				CampaignBudgetResponse cbRes = this.campaignClient.findCampaignBudget(user.getNick(),
						campaign.getAutoID());
				if (cbRes != null && cbRes.getRes() != null && cbRes.getRes().getBudget() != null) {
					CampaignBudgetDto tbBudgetDto = cbRes.getRes().getBudget();
					campaign.setBudget(tbBudgetDto.getBudget());
					campaign.setUseSmooth(tbBudgetDto.isUseSmooth());
					campaign.setUpdatedTime(new Date());
					log.info("****推广计划findCampaignBudget****: {}", campaign);
					this.campaignRepository.save(campaign);
				}
				if (cbRes != null && cbRes.getError() != null && cbRes.getError().getSubMessage() != null) {
					log.error("findCampaignBudget : {}", cbRes.getError().getSubMessage());
				}

			}

			if (dto.getArea() != null) {
				log.debug("sync campaign area: {}", campaign);
				String areaString = CampaignUtils.fromArea(dto.getArea());
				UpdateCampaignAreaResponse ucaRes = this.campaignClient.updateCampaignArea(user.getNick(),
						campaign.getAutoID(), areaString);
				if (ucaRes != null && ucaRes.getRes() != null && ucaRes.getRes().getArea() != null) {
					CampaignAreaDto tbAreaDto = ucaRes.getRes().getArea();
					campaign.setArea(CampaignUtils.toArea(tbAreaDto.getArea()));
					campaign.setUpdatedTime(new Date());
					log.info("****推广计划updateCampaignArea****: {}", campaign);
					this.campaignRepository.save(campaign);
				}
				if (ucaRes != null && ucaRes.getError() != null && ucaRes.getError().getSubMessage() != null) {
					log.error("updateCampaignArea : {}", ucaRes.getError().getSubMessage());
				}
			} else {
				CampaignAreaResponse caRes = this.campaignClient.findCampaignArea(user.getNick(), campaign.getAutoID());
				if (caRes != null && caRes.getRes() != null && caRes.getRes().getArea() != null) {
					CampaignAreaDto tbAreaDto = caRes.getRes().getArea();
					campaign.setArea(CampaignUtils.toArea(tbAreaDto.getArea()));
					campaign.setUpdatedTime(new Date());
					log.info("****推广计划findCampaignArea****: {}", campaign);
					this.campaignRepository.save(campaign);
				}
				if (caRes != null && caRes.getError() != null && caRes.getError().getSubMessage() != null) {
					log.error("findCampaignArea : {}", caRes.getError().getSubMessage());
				}
			}

			/*
			 * if (dto.getSchedule() != null) {
			 * log.debug("sync campaign schedule: {}", campaign); String
			 * areaString = CampaignUtils.fromArea(dto.getArea());
			 * UpdateCampaignScheduleResponse ucsRes =
			 * this.campaignClient.updateCampaignSchedule(user.getNick(),
			 * campaign.getAutoID(), areaString); if (ucsRes != null &&
			 * ucsRes.getRes() != null && ucsRes.getRes().getSchedule() != null)
			 * { CampaignScheduleDto tbScheduleDto =
			 * ucsRes.getRes().getSchedule(); //
			 * campaign.setSchedule(CampaignUtils.toSchedule(tbScheduleDto.
			 * getSchedule()));时间需要格式采用。
			 * campaign.setSchedule(tbScheduleDto.getSchedule());
			 * campaign.setUpdatedTime(new Date());
			 * log.info("****推广计划updateCampaignSchedule****: {}", campaign);
			 * this.campaignRepository.save(campaign); } if (ucsRes != null &&
			 * ucsRes.getError() != null && ucsRes.getError().getSubMessage() !=
			 * null) { log.error("updateCampaignSchedule : {}",
			 * ucsRes.getError().getSubMessage()); }
			 * 
			 * } else { CampaignScheduleResponse csRes =
			 * this.campaignClient.findCampaignSchedule(user.getNick(),
			 * campaign.getAutoID()); if (csRes != null && csRes.getRes() !=
			 * null && csRes.getRes().getSchedule() != null) {
			 * CampaignScheduleDto tbScheduleDto = csRes.getRes().getSchedule();
			 * // campaign.setSchedule(CampaignUtils.toSchedule(tbScheduleDto.
			 * getSchedule()));时间需要格式采用。
			 * campaign.setSchedule(tbScheduleDto.getSchedule());
			 * campaign.setUpdatedTime(new Date());
			 * log.info("****推广计划findCampaignSchedule****: {}", campaign);
			 * this.campaignRepository.save(campaign); } if (csRes != null &&
			 * csRes.getError() != null && csRes.getError().getSubMessage() !=
			 * null) { log.error("findCampaignSchedule : {}",
			 * csRes.getError().getSubMessage()); } }
			 */

			if (dto.getPlatform() != null) {
				dto.setCampaignID(campaign.getAutoID());
				log.debug("sync campaign platform: {}", dto);
				PlatformVo vo = new PlatformVo();
				vo.setCreateTime(campaign.getCreateTime());
				vo.setModifiedTime(campaign.getModifiedTime());
				vo.setNick(campaign.getNick());
				vo.setCampaignID(campaign.getAutoID());
				vo.setMobileDiscount(dto.getPlatform().getMobileDiscount());
				vo.setOutsideDiscount(dto.getPlatform().getOutsideDiscount());
				vo.setNonsearchChannels(new PlatformVo.Channels());
				vo.setSearchChannels(new PlatformVo.Channels());
				vo.getSearchChannels().setNumber(dto.getPlatform().toSearchChannels());
				vo.getNonsearchChannels().setNumber(dto.getPlatform().toNonsearchChannels());

				UpdateCampaignPlatformResponse ucpfRes = this.campaignClient.updateCampaignPlatform(user.getNick(),
						campaign.getAutoID(), dto.getPlatform().toSearchChannels(), vo.getOutsideDiscount(),
						vo.getOutsideDiscount());
				if (ucpfRes != null && ucpfRes.getRes() != null && ucpfRes.getRes().getPlatform() != null) {
					CampaignPlatformDto tbPlatformDto = ucpfRes.getRes().getPlatform();
					BeanUtils.copyProperties(vo, tbPlatformDto);
					tbPlatformDto.setCampaignID(campaign.getAutoID());
					tbPlatformDto.setMobileDiscount(vo.getMobileDiscount());
					tbPlatformDto.setNick(vo.getNick());
					tbPlatformDto.setNonsearchChannels(vo.getNonsearchChannels());
					tbPlatformDto.setOutsideDiscount(vo.getOutsideDiscount());
					tbPlatformDto.setSearchChannels(vo.getSearchChannels());

					campaign.setPlatform(platformService.serialize(vo));
					campaign.setUpdatedTime(new Date());
					log.info("****推广计划updateCampaignPlatform****: {}", campaign);
					this.campaignRepository.save(campaign);
				}
				if (ucpfRes != null && ucpfRes.getError() != null && ucpfRes.getError().getSubMessage() != null) {
					log.error("updateCampaignPlatform : {}", ucpfRes.getError().getSubMessage());
				}
			} else {
				dto.setCampaignID(campaign.getAutoID());
				log.debug("sync campaign platform: {}", dto);
				PlatformVo vo = new PlatformVo();

				CampaignPlatformResponse cpfRes = this.campaignClient.findCampaignPlatform(user.getNick(),
						campaign.getAutoID());
				if (cpfRes != null && cpfRes.getRes() != null && cpfRes.getRes().getPlatform() != null) {
					CampaignPlatformDto campaignPlatformDto = cpfRes.getRes().getPlatform();
					vo.setCreateTime(campaign.getCreateTime());
					vo.setModifiedTime(campaign.getModifiedTime());
					vo.setNick(campaign.getNick());
					vo.setCampaignID(campaignPlatformDto.getCampaignID());
					vo.setMobileDiscount(campaignPlatformDto.getMobileDiscount());
					vo.setNonsearchChannels(campaignPlatformDto.getNonsearchChannels());
					vo.setSearchChannels(campaignPlatformDto.getSearchChannels());
					vo.setOutsideDiscount(campaignPlatformDto.getOutsideDiscount());

					campaign.setPlatform(platformService.serialize(vo));
					campaign.setUpdatedTime(new Date());
					log.info("****推广计划findCampaignPlatform****: {}", campaign);
					this.campaignRepository.save(campaign);
				}
				if (cpfRes != null && cpfRes.getError() != null && cpfRes.getError().getSubMessage() != null) {
					log.error("findCampaignPlatform : {}", cpfRes.getError().getSubMessage());
				}

			}

			dto.setCampaignID(campaign.getAutoID());

			CampaignLog po = new CampaignLog();
			BeanUtils.copyProperties(campaign, po);
			po.setAction(CampaignLog.Action.ADD);
			po.setCampaignID(campaign.getAutoID());
			po.setUpdatedTime(new Date());
			try {
				po.setNote(this.objectMapper.writer().writeValueAsString(campaign));
			} catch (JsonProcessingException e) {
				log.error("JsonProcessingException: {}", e);
				po.setNote("");
			}

			this.campaignLogRepository.save(po);
			log.debug("sync campaign CampaignLog: {}", po);

		} else {
			log.error("fail createCampaign: {}", res.getError().getSubMessage());
		}

		log.debug("finish createCampaign: {}", dto);
		return dto;
	}

	@RequestMapping(method = RequestMethod.PUT, path = "/{campaign_id}")
	@ResponseBody
	public CampaignDto updateCampaign(@PathVariable("campaign_id") long campaignID, @RequestBody CampaignDto dto) {
		Campaign campaign = this.campaignRepository.findOne(campaignID);
		Assert.notNull(campaign, "campaign_not_found");

		log.debug("begin updateCampaign: {} {}", campaignID, dto);
		User user = this.userRepository.findOne(campaign.getUserID());
		if (user == null) {
			throw new IllegalArgumentException("user_not_foud");
		}

		if (dto.getBudget() >= 30 && dto.getBudget() != campaign.getBudget()) {
			CampaignVo cvo = new CampaignVo();
			cvo.setNewBudget(dto.getBudget());
			cvo.setOldBudget(campaign.getBudget());
			cvo.setCreateTime(campaign.getCreateTime());
			cvo.setModifiedTime(campaign.getModifiedTime());
			cvo.setAutoID(campaign.getAutoID());
			log.debug("sync campaign budget: {}", campaign);
			UpdateCampaignBudgetResponse ucbRes = this.campaignClient.updateCampaignBudget(user.getNick(),
					campaign.getAutoID(), dto.getBudget(), true);
			if (ucbRes != null && ucbRes.getRes() != null && ucbRes.getRes().getBudget() != null) {
				log.debug("updateCampaignBudget res: {}", ucbRes.getRes().getBudget());
				CampaignBudgetDto tbBudgetDto = ucbRes.getRes().getBudget();
				campaign.setBudget(tbBudgetDto.getBudget());
				campaign.setUseSmooth(tbBudgetDto.isUseSmooth());
				campaign.setUpdatedTime(new Date());
				this.campaignRepository.save(campaign);
				log.debug("campaign res: {}", campaign);

				CampaignLog po = new CampaignLog();
				BeanUtils.copyProperties(po, campaign);
				po.setCampaignID(campaign.getAutoID());
				po.setAction(CampaignLog.Action.UPDATE_BUDGET);
				po.setNewIntval(campaign.getBudget());
				po.setCampaignID(campaign.getAutoID());
				po.setUpdatedTime(new Date());
				try {
					po.setNote(this.objectMapper.writer().writeValueAsString(cvo));
				} catch (JsonProcessingException e) {
					log.error("JsonProcessingException: {}", e);
					po.setNote("");
				}

				this.campaignLogRepository.save(po);
				log.debug("sync campaign CampaignLog: {}", po);
			}

			if (ucbRes != null && ucbRes.getError() != null) {
				log.error("updateCampaignBudget:{}", ucbRes.getError().getMessage());
			}
		}

		if (dto.getArea() != null && !(dto.getArea().equals(campaign.getArea()))) {
			// CampaignVo cvo = new CampaignVo();
			// BeanUtils.copyProperties(campaign, cvo);
			// if (dto.getArea().isAsAll() == true) {
			//
			// } else if (campaign.getArea().isAsAll() == true) {
			//
			// } else {
			// List<Integer> addArea = new
			// ArrayList<Integer>(dto.getArea().getNums());
			// List<Integer> lessArea = new
			// ArrayList<Integer>(campaign.getArea().getNums());
			// addArea.removeAll(campaign.getArea().getNums());
			// lessArea.removeAll(dto.getArea().getNums());
			// cvo.setAddArea(new CampaignVo.Area());
			// cvo.getAddArea().setNums(addArea);
			// cvo.setLessArea(new CampaignVo.Area());
			// cvo.getLessArea().setNums(lessArea);
			// }
			log.debug("sync campaign area: {}||{}", campaign, dto);
			String areaString = CampaignUtils.fromArea(dto.getArea());
			UpdateCampaignAreaResponse ucaRes = this.campaignClient.updateCampaignArea(user.getNick(),
					campaign.getAutoID(), areaString);
			if (ucaRes != null && ucaRes.getRes() != null && ucaRes.getRes().getArea() != null) {
				CampaignAreaDto tbAreaDto = ucaRes.getRes().getArea();
				campaign.setArea(CampaignUtils.toArea(tbAreaDto.getArea()));
				campaign.setUpdatedTime(new Date());
				this.campaignRepository.save(campaign);
				log.debug("********campaign resArea********: {}", campaign);
				CampaignLog po = new CampaignLog();
				BeanUtils.copyProperties(po, campaign);
				po.setAction(CampaignLog.Action.UPDATE_AREA);
				po.setCampaignID(campaign.getAutoID());
				po.setUpdatedTime(new Date());
				po.setNote("");

				this.campaignLogRepository.save(po);
				log.debug("sync campaign CampaignLog: {}", po);
			}

			if (ucaRes != null && ucaRes.getError() != null) {
				log.error("updateCampaignArea: {}", ucaRes.getError().getMessage());
			}

		}

		if (dto.getScheduleObject() != null) {
			String schedule = CampaignUtils.fromScheduleObject(dto.getScheduleObject());
			dto.setSchedule(schedule);
		}
		if (dto.getSchedule() != null && dto.getSchedule().equals(
				"00:00-24:00:100;00:00-24:00:100;00:00-24:00:100;00:00-24:00:100;00:00-24:00:100;00:00-24:00:100;00:00-24:00:100")) {
			dto.setSchedule("all");
		}
		if (dto.getSchedule() != null && !(dto.getSchedule().equals(campaign.getSchedule()))) {
			CampaignVo cvo = new CampaignVo();
			cvo.setSchedule(CampaignUtils.toScheduleObject(dto.getSchedule()));
			log.debug("sync campaign schedule: {} ||{}", campaign, dto);
			UpdateCampaignScheduleResponse ucsRes = this.campaignClient.updateCampaignSchedule(user.getNick(),
					campaign.getAutoID(), dto.getSchedule());
			if (ucsRes != null && ucsRes.getRes() != null && ucsRes.getRes().getSchedule() != null) {
				CampaignScheduleDto tbScheduleDto = ucsRes.getRes().getSchedule();
				campaign.setUpdatedTime(new Date());
				campaign.setSchedule(tbScheduleDto.getSchedule());
				this.campaignRepository.save(campaign);
				log.debug("********campaign resSchedule********: {}", campaign);

				CampaignLog po = new CampaignLog();
				BeanUtils.copyProperties(po, campaign);
				po.setAction(CampaignLog.Action.UPDARE_SCHEDULE);
				po.setCampaignID(campaign.getAutoID());
				po.setUpdatedTime(new Date());
				try {
					po.setNote(this.objectMapper.writer().writeValueAsString(cvo));
				} catch (JsonProcessingException e) {
					log.error("JsonProcessingException: {}", e);
					po.setNote("");
				}

				this.campaignLogRepository.save(po);
				log.debug("sync campaign CampaignLog: {}", po);
			}

			if (ucsRes != null && ucsRes.getError() != null) {
				log.error("updateCampaignSchedule:{}", ucsRes.getError().getMessage());
			}
		}

		if (dto.getTitle() != null && !(dto.getTitle().equals(campaign.getTitle()))) {
			CampaignVo campaignVo = new CampaignVo();
			campaignVo.setOldTitle(campaign.getTitle());
			campaignVo.setNewTitle(dto.getTitle());
			campaignVo.setCreateTime(campaign.getCreateTime());
			campaignVo.setModifiedTime(campaign.getModifiedTime());
			campaign.setTitle(dto.getTitle());
			campaign.setUpdatedTime(new Date());
			this.campaignRepository.save(campaign);
			log.debug("********campaign resTitle********: {}", campaign);

			CampaignLog po = new CampaignLog();
			BeanUtils.copyProperties(po, campaign);
			po.setAction(CampaignLog.Action.UPDATE_TITLE);
			po.setCampaignID(campaign.getAutoID());
			po.setUpdatedTime(new Date());
			try {
				po.setNote(this.objectMapper.writer().writeValueAsString(campaignVo));
			} catch (JsonProcessingException e) {
				log.error("JsonProcessingException: {}", e);
				po.setNote("");
			}

			this.campaignLogRepository.save(po);
			log.debug("sync campaign CampaignLog: {}", po);
		}

		if (dto.getOnlineStatus() != null && !(dto.getOnlineStatus().equals(campaign.getOnlineStatus()))) {
			campaign.setOnlineStatus(dto.getOnlineStatus());
			campaign.setUpdatedTime(new Date());
			this.campaignRepository.save(campaign);
			log.debug("********campaign resOnlineStatus********: {}", campaign);

			CampaignLog po = new CampaignLog();
			BeanUtils.copyProperties(po, campaign);
			if (campaign.getOnlineStatus().getValue().equals("online")) {
				po.setAction(CampaignLog.Action.UPDATE_ONLINE_PAUSE);
			} else {
				po.setAction(CampaignLog.Action.UPDATE_ONLINE_OPEN);
			}
			po.setCampaignID(campaign.getAutoID());
			po.setUpdatedTime(new Date());
			po.setNote("");

			this.campaignLogRepository.save(po);
			log.debug("sync campaign CampaignLog: {}", po);
		}

		if (dto.getPlatform() != null) {
			PlatformVo vo = new PlatformVo();
			BeanUtils.copyProperties(campaign, vo);
			vo.setCampaignID(campaign.getAutoID());
			vo.setNick(campaign.getNick());
			this.toPlatformDto(dto, vo);
			try {
				dto.setPlatfromTemp(this.objectMapper.writer().writeValueAsString(vo));
			} catch (JsonProcessingException e) {
				log.error("JsonProcessingException: {}", e);
			}
		}

		if (dto.getPlatfromTemp() != null && !(dto.getPlatfromTemp().equals(campaign.getPlatform()))) {
			dto.setCampaignID(campaign.getAutoID());
			log.debug("sync campaign platform: {}", dto); // 到时改debug日志
			PlatformVo vo = new PlatformVo();
			BeanUtils.copyProperties(campaign, vo);
			vo.setCampaignID(campaign.getAutoID());
			vo.setNick(campaign.getNick());
			this.toPlatformDto(dto, vo);
			UpdateCampaignPlatformResponse ucpfRes = this.campaignClient.updateCampaignPlatform(user.getNick(),
					campaign.getAutoID(), dto.getPlatform().toSearchChannels(), vo.getOutsideDiscount(),
					vo.getMobileDiscount());
			if (ucpfRes != null && ucpfRes.getRes() != null && ucpfRes.getRes().getPlatform() != null) {
				CampaignPlatformDto tbPlatformDto = ucpfRes.getRes().getPlatform();
				BeanUtils.copyProperties(vo, tbPlatformDto);
				tbPlatformDto.setCampaignID(campaign.getAutoID());
				tbPlatformDto.setMobileDiscount(vo.getMobileDiscount());
				tbPlatformDto.setNick(vo.getNick());
				tbPlatformDto.setNonsearchChannels(vo.getNonsearchChannels());
				tbPlatformDto.setOutsideDiscount(vo.getOutsideDiscount());
				tbPlatformDto.setSearchChannels(vo.getSearchChannels());

				campaign.setPlatform(platformService.serialize(vo));
				campaign.setUpdatedTime(new Date());
				this.campaignRepository.save(campaign);
				log.debug("********campaign resPlatform********: {}||{}", campaign, ucpfRes);
				CampaignVo campaignVo = new CampaignVo();
				campaignVo.setAddPlatform(dto.getPlatform());
				CampaignLog po = new CampaignLog();
				BeanUtils.copyProperties(po, campaign);
				po.setAction(CampaignLog.Action.UPDATE_PLATFORM);
				po.setCampaignID(campaign.getAutoID());
				po.setUpdatedTime(new Date());
				try {
					po.setNote(this.objectMapper.writer().writeValueAsString(campaignVo));
				} catch (JsonProcessingException e) {
					log.error("JsonProcessingException: {}", e);
				}
				this.campaignLogRepository.save(po);
				log.debug("sync campaign CampaignLog: {}", po);
			}
			if (ucpfRes != null && ucpfRes.getError() != null) {
				log.error("updateCampaignPlatform : {}", ucpfRes.getError().getMessage());
			}
		}

		log.debug("finish updateCampaign: {} {}", campaignID, dto);
		dto.setCampaignID(campaignID);
		return dto;
	}

	public void toPlatformDto(CampaignDto dto, PlatformVo vo) {
		vo.setMobileDiscount(dto.getPlatform().getMobileDiscount());
		vo.setOutsideDiscount(dto.getPlatform().getOutsideDiscount());
		vo.setNonsearchChannels(new PlatformVo.Channels());
		vo.setSearchChannels(new PlatformVo.Channels());
		vo.getSearchChannels().setNumber(dto.getPlatform().toSearchChannels());
		vo.getNonsearchChannels().setNumber(dto.getPlatform().toNonsearchChannels());
	}

	// 查看某一个推广计划
	@RequestMapping(method = RequestMethod.GET, path = "/{campaign_id}")
	@ResponseBody
	public CampaignDto findCampaign(@PathVariable("campaign_id") long campaignID) {
		Campaign campaign = this.campaignRepository.findOne(campaignID);
		CampaignDto dto = new CampaignDto();
		BeanUtils.copyProperties(campaign, dto);
		dto.setCampaignID(campaign.getAutoID());
		dto.setAutoType(campaign.getAutoType().getValue());
		dto.setPlatform(new ConvertPlatformVo());
		PlatformVo vo = platformService.unserialize(campaign.getPlatform());
		dto.getPlatform().fromSearch(vo);
		dto.getPlatform().fromNonSearch(vo);
		dto.getPlatform().setMobileDiscount(vo.getMobileDiscount());
		dto.getPlatform().setOutsideDiscount(vo.getOutsideDiscount());

		log.debug("finish readCampaign: {}", dto);
		return dto;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@RequestMapping(method = RequestMethod.GET, path = "/{campaign_id}/actions")
	@ResponseBody
	public Page<LogDto<LogDto.LogNoteable>> findCampaignLog(@PathVariable("campaign_id") long campaignID,
			@RequestParam(name = "type", defaultValue = "campaign") String type,
			@RequestParam(name = "page_num", defaultValue = "0") int page,
			@RequestParam(name = "page_size", defaultValue = "50") int size) {
		PageRequest pr = new PageRequest(page, size);

		Page<LogDto<LogDto.LogNoteable>> dtos = null;
		Date today = DateUtils.truncate(new Date(), Calendar.DATE);
		SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm");

		if ("campaign".equals(type)) {
			Page<CampaignLog> logs = this.campaignLogRepository
					.findByCampaignIDAndUpdatedTimeAfterOrderByUpdatedTimeDesc(campaignID,
							DateUtils.addDays(today, -14), pr);
			List<LogDto<LogDto.LogNoteable>> list = new ArrayList<LogDto<LogDto.LogNoteable>>();
			for (CampaignLog clog : logs) {
				LogDto dto = new LogDto<CampaignVo>();
				BeanUtils.copyProperties(clog, dto);
				dto.setAction(clog.getAction().toDisplay());
				dto.setUpdatedTime(sdf.format(clog.getUpdatedTime()));
				if (!(clog.getNote().equals(""))) {
					try {
						dto.setNote(this.objectMapper.readerFor(CampaignVo.class).readValue(clog.getNote()));
					} catch (IOException e) {
						log.error("IOException: {}", e);
					}
				}
				list.add(dto);
			}
			dtos = new PageImpl<LogDto<LogDto.LogNoteable>>(list, pr, logs.getTotalElements());
		} else {
			Page<AdgroupLog> logs = this.adgroupLogRepository.findByCampaignIDAndUpdatedTimeAfterOrderByUpdatedTimeDesc(
					campaignID, DateUtils.addDays(today, -14), pr);
			List<LogDto<LogDto.LogNoteable>> list = new ArrayList<LogDto<LogDto.LogNoteable>>();
			for (AdgroupLog alog : logs) {
				LogDto dto = new LogDto<AdgroupVo>();
				BeanUtils.copyProperties(alog, dto);
				dto.setAction(alog.getAction().toDisplay());
				dto.setUpdatedTime(sdf.format(alog.getUpdatedTime()));
				if (!(alog.getNote().equals(""))) {
					try {
						dto.setNote(this.objectMapper.readerFor(AdgroupVo.class).readValue(alog.getNote()));
					} catch (IOException e) {
						log.error("IOException:{}", e);
					}
				}
				list.add(dto);
			}
			dtos = new PageImpl<LogDto<LogDto.LogNoteable>>(list, pr, logs.getTotalElements());
		}

		return dtos;

	}

	// 趋势图
	@RequestMapping("/{campaign_id}/reports/trend")
	public @ResponseBody Object reportsTrend(@PathVariable("campaign_id") Long campaignId,
			@RequestParam(defaultValue = "7") Integer days, @RequestParam(required = false) Integer device,
			@RequestParam(required = false) String startDate, @RequestParam(required = false) String endDate) {
		log.info("reportsTrend RequestParam campaignId:{} days:{} device:{} startDate:{} endDate:{}", campaignId, days,
				device, startDate, endDate);
		RptKeywordParam param = new RptKeywordParam();
		param.setUserId(campaignRepository.findOne(campaignId).getUserID());
		param.setCampaignId(campaignId);
		if (device != null) {
			param.setSource(device.byteValue());
		}
		param.setDay(days);
		param.setStartDate(startDate);
		param.setEndDate(endDate);
		return rptKeywordService.getReportsTrendByDate(param);
	}

	// 指标摘要
	@RequestMapping("/{campaign_id}/summaries/metric")
	public @ResponseBody Object summariesMetric(@PathVariable("campaign_id") Long campaignId,
			@RequestParam(defaultValue = "7") Integer days, @RequestParam(required = false) Integer device,
			@RequestParam(required = false) String startDate, @RequestParam(required = false) String endDate) {
		log.info("summariesMetric RequestParam campaignId:{} days:{} device:{} startDate:{} endDate:{}", campaignId,
				days, device, startDate, endDate);
		RptKeywordParam param = new RptKeywordParam();
		param.setUserId(campaignRepository.findOne(campaignId).getUserID());
		param.setCampaignId(campaignId);
		if (device != null) {
			param.setSource(device.byteValue());
		}
		param.setDay(days);
		param.setStartDate(startDate);
		param.setEndDate(endDate);
		return rptKeywordService.getSummariesMetric(param);
	}

	// 推广组数据
	@RequestMapping("/{campaign_id}/adgroupStates")
	public @ResponseBody Object adgroupStates(@PathVariable("campaign_id") Long campaignId,
			@RequestParam(defaultValue = "7") Integer days, @RequestParam(required = false) Integer device,
			@RequestParam(required = false) String startDate, @RequestParam(required = false) String endDate) {
		log.info("adgroupStates RequestParam campaignId:{} days:{} device:{} startDate:{} endDate:{}", campaignId, days,
				device, startDate, endDate);
		RptKeywordParam param = new RptKeywordParam();
		param.setUserId(campaignRepository.findOne(campaignId).getUserID());
		param.setCampaignId(campaignId);
		if (device != null) {
			param.setSource(device.byteValue());
		}
		param.setDay(days);
		param.setStartDate(startDate);
		param.setEndDate(endDate);
		return rptKeywordService.getReportsTrend(param);
	}

	@Data
	@JsonInclude(Include.NON_NULL)
	public static class CampaignDto {

		@JsonProperty("campaign_id")
		private long campaignID;

		@JsonProperty("user_id")
		private long userID;

		private int budget;

		private String title;
		private int autoType;

		private Area area;

		private OnlineStatus onlineStatus;

		// private Schedule schedule; 时间需要格式，采用的方式
		@JsonProperty("schedule_object")
		private ScheduleObject scheduleObject;

		private String schedule;

		private String platfromTemp;

		private ConvertPlatformVo platform;
	}

	@RequestMapping(method = RequestMethod.GET, path = "/{campaign_id}/keywords")
	@ResponseBody
	public ListResponse<Keyword> findKeywords(@PathVariable("campaign_id") long campaignID,
			@RequestParam(name = "filters", defaultValue = "max_price") List<String> filters,
			@RequestParam(name = "max_price", required = false, defaultValue = "0") int maxPrice) {

		List<Adgroup> adgroups = this.adgroupRepository.findByCampaignID(campaignID);

		ListResponse<Keyword> dto = new ListResponse<Keyword>();
		dto.setDatas(new ArrayList<Keyword>());
		int adgroupCount = 0;
		for (Adgroup adgroup : adgroups) {
			if (adgroup.getLimit() == 0) {
				throw new IllegalArgumentException("no_limit");
			}
			KeywordExample ex = new KeywordExample();
			ex.setUserId(adgroup.getUserID());
			ex.createCriteria().andAdgroupIdEqualTo(adgroup.getAutoID());
			List<Keyword> keywords = this.keywordMapper.selectByExample(ex);
			for (Keyword key : keywords) {
				boolean canAdd = true;
				if (filters != null) {
					if (filters.indexOf("max_price") > 0) {
						canAdd = canAdd && (maxPrice < key.getMaxMobilePrice() || maxPrice < key.getMaxPrice());
					}
				}
				if (canAdd) {
					dto.getDatas().add(key);
				}
			}
			if (dto.getTemp() != dto.getDatas().size()) {
				adgroupCount++;
			}
			dto.setTemp(dto.getDatas().size());
		}
		dto.setTemp(dto.getDatas().size()); // 统计的是关键词要修改的总数
		dto.setTotal(adgroupCount);
		dto.setStatus(true);

		return dto;
	}
}
